/**
 * @author killer-g
 * @version 0.2 alpha
 * @projectDescription Concat and compress a jamal framework
 * Select a jamal directory with expected structure of
 * 
 * js/
 * 		/jamal/				-> holding the jamal core files
 * 			components 		-> core wide components
 * 			libs 			-> core libs
 * 			plugins 		-> jQuery plugins
 *  
 *  
 *  	/app/			-> your application specific code
 *  		models 		-> you models
 *  		controllers
 *  		views
 * 
 *   first the jamal core framwork (js/jamal/*) is packed into a solid file into the main dir (js)
 *   
 *   The processing sequence is the following:
 *   - readIntro();
 *   - readJamal();
 *   - readLibs();
 *   - readComponents();
 *   - readStartup();
 *   - readPlugins();
 *   - readOutro();
 *   
 *   next level will be the packagin of the whole app dir including jamal core
 * 
 * Internal coding hints:
 * 	Not working jQuery selectors:
 * 		remove
 * 		slideDown Slow with hidden elementes -> display:none;
 */


/**
 * the directory where the jamal code resides
 * this is the top js directory 
 * Object
 */
var directory = null;

/**
 * the content of the js files will be appended to this file 
 * before the compression takes place
 */
var tmp_file = null;

/**
 * the array holding the current handled files [0]=> windows/file/path/
 */
var files_db =[];

/**
 * temp string object with ul/li list of current files/dirs which is rendered into the fronentd
 */
var html_list = "";

/**
 * temp string object with xml nodes list which is rendered into a static xml config file for saving
 */
var xml_list = "";


/**
 * initial on load 
 * setting events and handlers to buttons 
 */
function doLoad()
{
		
	console.log(navigator.userAgent);
	
	directory = air.File.documentsDirectory;
	directory.addEventListener( air.Event.SELECT, doSelect );
		
	//add browse button event
	document.getElementById( "btnBrowse" ).addEventListener( "click", doBrowse );	
	
	//add save button even
	document.getElementById( "btnPackJamal" ).addEventListener( "click", startBuildProcess );
	//add drag enter event
	window.htmlControl.addEventListener(air.DragEventENTER, doEnter ); // runtime.flash.events.NativeDragEvent.NATIVE_DRAG_ENTER
	//dragging out of range
	window.htmlControl.addEventListener( air.DragEventEXIT, doDragExit );
	//add drag drop event
	window.htmlControl.addEventListener( runtime.flash.events.NativeDragEvent.NATIVE_DRAG_DROP, doDrop );
}

/**
 * open the the native browse for file dialog
 */
function doBrowse()
{
	directory.browseForDirectory( "Select jamal directory:" );
}
	
/**
 * after a directory is selected in the native filedialog
 */
function doSelect()
{
	//clear existing list values
	$('#fileList').empty();
	html_list = '';
		
	generateHtmlTree( directory);
	
	$('#fileList').append(html_list);
	
	$('#fileList').Treeview({
		speed: "fast",
		collapsed: true,
		unique: true,
		store: false			
	});		

}
/**
 * read the core jamal js and compress them into a solid packed version
 *  
 *  concat files in this order:
 *		intro.js
 *		jamal.js
 *		libs/*.js
 *		components/*.js
 *		startup.js
 *		plugins/*.js
 *		outro.js
 *    
 */
function startBuildProcess()
{	
	console.log("Start startBuildProcess");
	//create new temp file
	tmp_file = air.File.createTempFile( );
	console.log(tmp_file.nativePath);
	//start the process
	readIntro();	
} 


/****************************************************
 * Start processing
****************************************************/

/**
 * read the intro file
 * @param {Object} base_dir
 */
function readIntro()
{
	console.log("Start readIntro");
	//READ
	var data 	= readFile("/jamal/intro.js");

	//WRITE
	tmp_stream = new air.FileStream();
	tmp_stream.open( tmp_file, air.FileMode.APPEND );	
	//append data to temp file
	tmp_stream.writeMultiByte(data, air.File.systemCharset );
	tmp_stream.close();	
	
	//on to next
	readJamal();
	
}


function readJamal()
{
	console.log("Start readJamal");
	var data 	= readFile("/jamal/jamal.js");
	var ok = appendToTempFile(data);
	if(ok == true)
	{//on to next
		readLibs();	
	}
	else
	{//some error handling here
	
		
	}
}
/**
 * read content of /libs folder
 */
function readLibs()
{
	console.log("Start readLibs");
	
	var base_dir 	= directory.nativePath;		
	var data 		= null;
	var ok	 		= null;
	
	var dir 		= new air.File();
	dir			 	= dir.resolve(base_dir + "/jamal/libs/" );	
	var files 		= dir.listDirectory();	

	
	for (i = 0; i < files.length; i++) 
	{// each file in libs
		if(files[i].name.substring(files[i].name.length-3) == '.js')   
		{//parking only js
	    	console.log("read Lib:" + files[i].name);
			//READ			
			data = readFile(files[i]);			
			//WRITE
			ok = appendToTempFile(data);	
		 	//need some error check here				
		}
				
	}
	console.log("end readLibs");
	//pass it on to the component reader
	readComponents();	
	
}
/**
 * read the content of the components folder and appen each file to the temp file
 */
function readComponents()
{
	console.log("Start readComponents");
	
	var base_dir 	= directory.nativePath;	
	var data 		= null;
	var ok 			= null;

	var dir 		= new air.File();
	dir			 	= dir.resolve(base_dir + "/jamal/components/" );	
	var files 		= dir.listDirectory();	

	for (i = 0; i < files.length; i++) 
	{//for each file in libs
		if(files[i].name.substring(files[i].name.length-3) == '.js')  
		{//only do this for shiny js files			
			//READ	
			data = readFile(files[i]);
			//WRITE
			ok = appendToTempFile(data);	
		 	//need some error check here		
		}				
	}
	
	console.log("End readComponents");
	readStartup();
	
}
/**
 * read the content of the components folder and appen each file to the temp file
 */
function readStartup()
{
	console.log("Start readStartup");	
	//READ	
	var data = readFile("/jamal/startup.js");	
	//WRITE
	var ok = appendToTempFile(data);
	if(ok == true)
	{
		console.log("End readStartup");
		readPlugins();	
	}
	else
	{//some error handling here
		
	}				
}

/**
 * read the contents of the plugins directory
 * watch out there is no check for subdirectories right now
 */
function readPlugins()
{
	console.log("Start readPlugins");
	
	var base_dir 	= directory.nativePath;	
	var data 		= null;
	var ok 			= null;

	var dir 		= new air.File();
	dir			 	= dir.resolve(base_dir + "/jamal/plugins/" );	
	var files 		= dir.listDirectory();	

	for (i = 0; i < files.length; i++) 
	{//for each file in libs
		if(files[i].name.substring(files[i].name.length-3) == '.js')  
		{//only do this for shiny js files			
			//READ	
			data = readFile(files[i]);
			//WRITE
			ok = appendToTempFile(data);	
		 	//need some error check here		
		}				
	}
	console.log("End readPlugins");
	readOutro();
	
}
/**
 * read the closer file, which just contains a closing bracket
 */
function readOutro()
{
	console.log("Start readOutro");
	//READ	
	var data = readFile("/jamal/outro.js");		
	//WRITE
	var ok = appendToTempFile(data);
			
	if(ok == true)
	{//onto next
		console.log("End readOutro");
		moveTempFile();	
	}
	else
	{//some error handling here		
		
	}	
}

function moveTempFile()
{
	console.log("Start moveTempFile");
	var base_dir		= directory.nativePath;
	var jamal_debug  = directory.resolve(base_dir + "/jamal_debug.js");
	
	try  
	{
	    tmp_file.moveTo(jamal_debug, true);
		
	}
	catch (error)
	{
		console.log("Error:" + error.message);
	}
	finally
	{
		$('#success').append('<p><strong>Jamal debug version:</strong> <br />' + jamal_debug.nativePath);
	
		compressJamalCore();		
	}
}

function compressJamalCore()
{
	console.log('Start compressJamalCore');
	var base_dir	= directory.nativePath;
	var stream		= null;	
	var packed_file	= new air.File();
	var packed_data	= null;
	
	//READ	
	var data = readFile("/jamal_debug.js");
		
	//the packing .. pretty short for what it does :-)
	packed_data = pack( data, 62, true, false );
	
	console.log(packed_data);
	
	//init packed_file;	
	packed_file		= packed_file.resolve(base_dir + '/jamal_packed.js' );
	
	//WRITE
	stream = new air.FileStream();
	stream.open( packed_file, air.FileMode.WRITE );	
	//append data to temp file
	stream.writeMultiByte(packed_data, air.File.systemCharset );
	//close both streams
	stream.close();	
	$('#success').empty();
	$('#success').append('<p><strong>Packed Jamal to:</strong> <br />' + packed_file.nativePath + '<br /> <h2>Now hit the Javascript MVC Road!</h2>');
	//add xml save
	var config_save_html = '<br />'+
						'<input id="configName" type="text" value="Projectname" /> '+
						'<input id="btnSaveConfig" type="button" value="Save Project" />';
	$('#btnStartBuildProcess').after(config_save_html);
	document.getElementById( "btnSaveConfig" ).addEventListener( "click", doSaveXml );	
	
	console.log('end compressJamalCore');
	
}

/****************************************************
 * END processing
****************************************************/

/****************************************************
 * Start MVC Templates
****************************************************/

/**
/**
 * build some bloody empty files ??? 
 * yead dude template driven Jamal Building ... rock�n roll
 */
function generateAppMvcTemplates()
{
	
	
}

/**
 * return the content of the template model file
 * 
 * @param String model_name
 * @return String - the text to be written into the models file
 */
function getModelTemplate(model_name)
{
	var text = "";
	return text;
}

/**
 * return the content of the template Controller file 
 * @param String model_name
 * @return String - the text to be written into the models file
 */
function getControllerTemplate(controller_name)
{
	var text = "";
	return text;
}
/**
 * return the content of the View template file 
 * @param String model_name
 * @return String - the text to be written into the models file
 */
function getViewTemplate(view_name)
{
	var text = "";
	return text;
}

/****************************************************
 * Actions for events
****************************************************/
/**
 * when a file is dragged over the air window
 */
function doEnter(e)
{

	if( e.transferable.hasFormat( air.TransferableFormats.FILE_LIST_FORMAT ) )
	{
		air.DragManager.acceptDragDrop( window.htmlControl );
		
		$('#fileIncoming').append('Watch it babe ... Jamal Directory incoming');
		$('#fileIncoming').slideDown('slow');
		$('#fileIncoming').css('visibility','visible');		
	}
	
}
/**
 * when a formerly dragged over file is dragged away for the air window
 */
function doDragExit(e)
{
	$('#fileIncoming').slideUp();
	$('#fileIncoming').empty();
}


/**
 * when a folder is dropped in the air window
 */
function doDrop(e)
{	
	var files = e.transferable.dataForFormat( air.TransferableFormats.FILE_LIST_FORMAT, air.TransferableTransferMode.ORIGINAL_PREFERRED );

	if(files.length == 1 && files[0].isDirectory)
	{//only allow one folder
		//clear files/xml/ul list
		$('#fileList').empty();
		html_list = '';
		xml_list = '';
		
		//set global home directory
		directory = files[0];
		//remove drop box
		$('#fileIncoming').slideUp();
		$('#fileIncoming').empty();	
			
		generateHtmlTree(directory);
		
		$('#fileList').append(html_list);
		
		$('#fileList').Treeview({
			speed: "fast",
			collapsed: true,
			unique: true,
			store: false			
		});				
	}
	else
	{
		error_msg('Please drag only one Directory onto this Window.');
	}	
}
/**
 * save a proct into an xml file
 * 
 * needed nodes
 * 	- path
 *  - 
 * 
 */
function doSaveXml()
{
	console.log('Start doSaveXml');

	var filename = '';
	
	filename = $('#configName').val();
	filename +=  '_config.xml';
	
	//var file	= new air.File();
	var file = air.File.applicationStorageDirectory.resolve(filename );
	
	var stream = new air.FileStream();	
	
	console.log(file.nativePath);
	
	generateXmlTree(directory);

	stream.open( file, air.FileMode.WRITE );
	
	xml_list = xml_list.replace(/\n/g, air.File.lineEnding);

	stream.writeUTF(xml_list);
	
	stream.close();	

}

/****************************************************
 * Helpers 
****************************************************/
/**
 * read a single file and return its contents
 * @param {MIXED} file - STRING - the filename or a path/filename.js
 * 									in this case a new file object will be created
 * 						OBJECT - an existing file object
 */
function readFile(file)
{
	//console.log(typeof file);

	if(typeof file == 'string')
	{//passed a filename string in so need to make a new fileobject
		var filename 	= file;	//cosmetics
		var base_dir	= directory.nativePath;
		var file 	 	= new air.File();
		file 			= file.resolve(base_dir + filename );
	}	
	
	var stream = new air.FileStream();
	stream.open( file, air.FileMode.READ );
	data = stream.readMultiByte(file.size, air.File.systemCharset);
	stream.close();	

	return data;
}


/**
 * append content to the temp file
 * @param {String} data - the date to append to
 */
function appendToTempFile(data)
{
	console.log("Start appendToTempFile");
	
	var tmp_stream = new air.FileStream();
	tmp_stream.open( tmp_file, air.FileMode.APPEND );	
	//append data to temp file
	tmp_stream.writeMultiByte(data, air.File.systemCharset );
	tmp_stream.close();	
	
	return true;	
}

/**
 * listing all files inside a directory and append them to the global files_db array
 * this function is callings itself recursivly if it finds a subdirectory
 * 
 * @param {Object} dir - directory object
*/
function readDirectory(dir)
{
	var name = null;
	var subdir = null;
	
	for( var i = 0; i < dir.length; i++ )
	{//each file in directory				
		if(dir[i].isDirectory)
		{ //recurse into directory
			subdir = dir[i].listDirectory();
			readDirectory(subdir);			
		}
		else
		{//its a file
			name = dir[i].name;
			files_db.push(name);			
		}				
	}	
} 

/**
 * takes a single top directory and recursivly builds up an ul/li list
 * <ul>
 * <li><img src="img/folder.gif" />Item 1
 * 	<ul>
 *	   <li><img src="img/file.gif" />Item 1.1</li>
 *	</ul>
 *	</li>
 * </ul>
 * function taken from http://www.devx.com/xml/Article/11866/1954?pf=true
 * @param {Object} dir
 */
function generateHtmlTree(file_oject)
{	
	if(file_oject.isDirectory)
	{//got a freakin directory
		html_list +='<li><img src="img/folder.gif" /> ' +file_oject.name + '<ul>';
			
		var sub_nodes= file_oject.listDirectory();		
		for(var i=0; i<sub_nodes.length; i++)
		{
			console.log(sub_nodes[i].name);
			generateHtmlTree(sub_nodes[i]);			
		}
        html_list +='</li></ul>';		
	}
	else
	{//its a file
		html_list +='<li><img src="img/file.gif" /> ' + file_oject.name + '</li>';
	}	
}
/**
 * takes a single top directory and recursivly builds up an ul/li list
 * <ul>
 * <li><img src="img/folder.gif" />Item 1
 * 	<ul>
 *	   <li><img src="img/file.gif" />Item 1.1</li>
 *	</ul>
 *	</li>
 * </ul>
 * function taken from http://www.devx.com/xml/Article/11866/1954?pf=true
 * @param {Object} dir
 */
function generateXmlTree(file_oject)
{	
	if(file_oject.isDirectory)
	{//got a freakin directory
		xml_list +='\n<dir> ' + file_oject.name + '\n';
			
		var sub_nodes= file_oject.listDirectory();		
		for(var i=0; i<sub_nodes.length; i++)
		{
			generateXmlTree(sub_nodes[i]);			
		}
        xml_list +='\n</dir>';	
	}
	else
	{//its a file
		xml_list +='\n<file> ' + file_oject.name + '</file>';
	}	
}

/**
 * output the error message to the error div
 * @param {Object} msg
 */
function error_msg(msg)
{
	$('#error_msg ul').append('<li>' + msg + '</li>');
}